﻿//using System;
//using System.Collections.Generic;
//using System.Text;
//using Microsoft.ML;
//using Microsoft.ML.AutoML;
//using Microsoft.ML.Data;
//using Microsoft.ML.Trainers;

//ML.net 不灵，换个convnet
//namespace JustMathCore.ML
//{
//    public class InputSlot
//    {
//        [Microsoft.ML.Data.VectorType(4)]
//        public float[] input4bit;
//        public float result;
//    }
//    public class Input
//    {
//        public List<IEnumerable<InputSlot>> slots = new List<IEnumerable<InputSlot>>();
//    }
//    public class Result
//    {
//        [ColumnName("Score")]
//        public float predict;
//    }
//    public static class Bot
//    {
//        private static uint ExperimentTime = 60;
//        static MLContext mlContext = new MLContext();
//        static ITransformer pipeline;
//        static string modelfile;
//        /// <summary>
//        /// 从一个路径初始化机器人，若不存在，则用初始化训练数据训练
//        /// </summary>
//        /// <param name="path"></param>
//        /// <param name="inittraindata"></param>
//        /// <returns></returns>
//        public static bool Init(string path)
//        {
//            var finalpath = System.IO.Path.GetFullPath(path) + "\\model";
//            if (System.IO.Directory.Exists(finalpath) == false)
//                System.IO.Directory.CreateDirectory(finalpath);

//            modelfile = finalpath + "\\model.zip";

//            try
//            {
//                pipeline = mlContext.Model.Load(modelfile, out DataViewSchema schema);
//                return true;
//            }
//            catch
//            {
//                return false;
//            }
//        }
//        static InputSlot EncodeToSlot(byte[] src, byte[] dest, int slotindex)
//        {
//            InputSlot slot = new InputSlot();
//            slot.input4bit = new float[4];
//            for (var i = 0; i < slot.input4bit.Length / 2; i++)
//            {
//                slot.input4bit[i * 2] = src[i] % 16;
//                slot.input4bit[i * 2 + 1] = src[i] / 16;
//            }

//            var value = dest[slotindex / 2];
//            if (slotindex % 2 == 1)//高位
//            {
//                value = (byte)(value / 16);
//            }
//            else
//            {
//                value = (byte)(value % 16);
//            }
//            slot.result = value;

//            return slot;
//        }
//        public static Input GenRandomInput(JustMathCore.AddrTools.AddrType addrtype, int count)
//        {
//            Input input = new Input();
//            var conv = AddrTools.GetConv(addrtype);
//            //init slot
//            int slotcount = 1;
//            for (var i = 0; i < slotcount; i++)
//            {
//                var slot = new List<InputSlot>();
//                input.slots.Add(slot);
//            }

//            Random ran = new Random();
//            for (var i = 0; i < count; i++)
//            {
//                byte[] prikey = new byte[32];
//                ran.NextBytes(prikey);
//                byte[] addr = conv.GetHashAddr(prikey);
//                for (var si = 0; si < slotcount; si++)
//                {
//                    var slot = input.slots[si] as List<InputSlot>;
//                    slot.Add(EncodeToSlot(addr, prikey, si));
//                }
//            }
//            return input;
//        }
//        //训练
//        public static void Fit(Input input)
//        {
//            if (pipeline == null)//没管线 先初始化
//            {
//                var data = mlContext.Data.LoadFromEnumerable(input.slots[0]);
//                Console.WriteLine("begin init train");
//                using (var ms = new System.IO.MemoryStream())
//                {
//                    mlContext.Data.SaveAsText(data, ms);
//                    System.IO.File.WriteAllBytes("d:\\out.txt", ms.ToArray());
//                }

//                var handler = new RegressionExperimentProgressHandler();
//                var result = mlContext.Auto().CreateRegressionExperiment(ExperimentTime).Execute(data, "result"
//                    , progressHandler: handler);


//                foreach (var r in result.RunDetails)
//                {
//                    if (r.ValidationMetrics == null)
//                        continue;
//                    Console.WriteLine("model=" + r.Model);
//                    Console.WriteLine("   loss=" + r.ValidationMetrics.LossFunction);
//                    Console.WriteLine("   rsquared=" + r.ValidationMetrics.RSquared);
//                }
//                RunDetail<RegressionMetrics> best = result.BestRun;
//                Console.WriteLine("best loss=" + best.ValidationMetrics.LossFunction);
//                Console.WriteLine("best rsquared=" + best.ValidationMetrics.RSquared);
//                pipeline = best.Model;
//                mlContext.Model.Save(pipeline, data.Schema, modelfile);
//                Console.WriteLine("finish init train");
//            }
//            else
//            {
//                LinearRegressionModelParameters originalModelParameters =
//    ((ISingleFeaturePredictionTransformer<object>)pipeline).Model as LinearRegressionModelParameters;

//                var newdata = mlContext.Data.LoadFromEnumerable(input.slots[0]);
//                //持续训练
//                var retraindmodel = mlContext.Regression.Trainers.OnlineGradientDescent().Fit(newdata, originalModelParameters);

//            }

//        }
//        public static void Test(Input input)
//        {
//            var data = mlContext.Data.LoadFromEnumerable(input.slots[0]);
//            var predict = mlContext.Model.CreatePredictionEngine<InputSlot, Result>(pipeline);
//            var slots = input.slots[0];
//            int right = 0;
//            int count = 0;
//            foreach (var s in slots)
//            {
//                //s.result = 0;
//                var result = predict.Predict(s);
//                if ((int)(result.predict + 0.5) == (int)s.result)
//                {
//                    right++;
//                }
//                count++;
//                Console.WriteLine("result.score=" + result.predict);
//            }
//            Console.WriteLine("right=" + right + "/" + count);

//        }
//    }

//    public class RegressionExperimentProgressHandler : IProgress<RunDetail<RegressionMetrics>>
//    {
//        private int _iterationIndex;

//        public void Report(RunDetail<RegressionMetrics> iterationResult)
//        {
//            if (_iterationIndex++ == 0)
//            {
//                Console.WriteLine("report header");
//            }

//            if (iterationResult.Exception != null)
//            {
//                Console.WriteLine("report error:" + iterationResult.Exception);
//            }
//            else
//            {
//                Console.WriteLine("index=" + _iterationIndex +
//                    ",name=" + iterationResult.TrainerName +
//                    ",metrics=" + iterationResult.ValidationMetrics +
//                    ",time=" + iterationResult.RuntimeInSeconds);
//            }
//        }
//    }
//}
